<?php
/**
 * Created by PhpStorm.
 * User: 小灰灰
 * Date: 2023-11-16
 * Time: 15:14:08
 * Info: 网站地图控制器
 */

namespace app\admin\controller;

use think\App;
use think\facade\View;
use think\facade\Cookie;
use app\common\model\Models as ModelsModel;
use app\common\model\Category as CategoryModel;
use app\common\model\Keywords as KeywordsModel;
use app\common\model\Content as ContentModel;

class Sitemap extends Base
{

    protected $root_dir;

    protected $data;

    protected $filename;

    protected $header;

    protected $footer;

    public function __construct(App $app)
    {
        parent::__construct($app);
        $this->root_dir = public_path();
        $this->data     = [];
        $this->filename = 'sitemap.xml';
        $this->header   = '<?xml version="1.0" encoding="UTF-8"?>'."\n".'<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">'."\n";
        $this->footer   = '</urlset>';
    }

    public function index()
    {
        $is_make_xml   = $is_make_txt = false;
        $make_xml_time = $make_txt_time = "";

        $fileXml = public_path()."sitemap.xml";
        if (is_file($fileXml)) {
            $is_make_xml   = true;
            $make_xml_time = date('Y-m-d H:i:s', filemtime($fileXml));
        }

        $fileTxt = public_path()."sitemap.txt";
        if (is_file($fileTxt)) {
            $is_make_txt   = true;
            $make_txt_time = date('Y-m-d H:i:s', filemtime($fileTxt));
        }

        $modelsList = ModelsModel::getModelsIdMenuList();

        View::assign('is_make_xml', $is_make_xml);
        View::assign('is_make_txt', $is_make_txt);
        View::assign('make_xml_time', $make_xml_time);
        View::assign('make_txt_time', $make_txt_time);
        View::assign('models_list', $modelsList);

        return View::fetch();
    }

    /**
     * 生成地图
     */
    public function make_sitemap()
    {
        if ($this->request->isPost()) {
            $param = $this->request->param();
            if (empty($param['model_id'])) {
                $this->error("请选择模型");
            }
            $model_id    = $param['model_id'];
            $limit_total = $param['limit_total'] ?? 0;
            $change_freq = $param['change_freq'] ?? "weekly";
            $priority    = $param['priority'] ?? 0.8;
            $type        = $param['type'] ?? 1;
            $total       = $param['type'] ?? 0;
            $page        = 1;
            $pagesize    = 300;
            $time        = time();
            if ($type) {
                $this->filename = 'sitemap.txt';
            }

            $site_url = get_config('site_url');

            if ($page == 1) {
                // 第一次写入时
                @file_put_contents($this->root_dir.$this->filename, $type ? '' : $this->header);

                // 生成首页链接
                $item = $this->_sitemap_item($site_url, $time, 'daily', '1.0');
                $this->_add_data($item);

                // 生成栏目链接
                $data = (new CategoryModel())->tpCateListTree("", "", "", "sort asc,id asc", 0);
                foreach ($data as $val) {
                    if ( ! strpos($val['href'], '://')) {
                        $val['href'] = $site_url.ltrim($val['href'], '/');
                    }
                    $item = $this->_sitemap_item($val['href'], $time, $change_freq, $priority);
                    $this->_add_data($item);
                }

                // 生成TAG链接
                $data = KeywordsModel::field('id')->where(['status' => 1])->order('id desc')->limit(300)->select();
                foreach ($data as $val) {
                    $item = $this->_sitemap_item($site_url."search/tag/id/".$val['id'], $time, $change_freq, $priority);
                    $this->_add_data($item);
                }
            }

            // 生成内容链接
            if ( ! $total) {
                $total = ContentModel::where(['model_id' => $model_id, 'status' => 1])->count();
                $total = $limit_total ? min($limit_total, $total) : $total;
            }
            $num    = ceil($total / $pagesize);
            $page   = max($page, 1);
            $offset = $pagesize * ($page - 1);

            $data = ContentModel::field('id,publish_time')->where([
                'model_id' => $model_id,
                'status'   => 1
            ])->order("id desc")->limit($offset, $pagesize)->select();
            foreach ($data as $val) {
                if ( ! strpos($val['url'], '://')) {
                    $val['url'] = $site_url.ltrim($val['url'], '/');
                }
                $url  = $site_url."index/show/id/".$val['id'];
                $item = $this->_sitemap_item($url, $val['publish_time'], $change_freq, $priority);
                $this->_add_data($item);
            }

            $str    = $type ? $this->_txt_format() : $this->_xml_format();
            $strlen = @file_put_contents($this->root_dir.$this->filename, $str, FILE_APPEND | LOCK_EX);
            if ( ! $strlen) {
                $this->error('生成文件 '.$this->filename.' 失败，请检查是否有写入权限！');
            }

            if ($num <= $page) {
                if ( ! $type) {
                    @file_put_contents($this->root_dir.$this->filename, $this->footer, FILE_APPEND | LOCK_EX);
                }
                $this->success('生成文件 '.$this->filename.' 成功！');
            }

            $rate = round(100 * ($page * $pagesize / $total), 2);
            $this->json(['code' => 2, 'msg' => '正在生成中，进度'.$rate.'%……', 'total' => $total, 'page' => $pages]);
        }
        $this->error('请求失败');
    }

    /**
     * 删除文件
     * @return void
     */
    public function delete()
    {
        $type = $this->request->param('type');
        if (empty($type)) {
            $this->error('参数错误');
        }
        $file = $this->root_dir."sitemap.".$type;
        if (file_exists($file)) {
            if (unlink($file)) {
                $this->success('删除成功');
            } else {
                $this->error('删除失败');
            }
        }
        $this->success('删除成功');
    }

    /**
     * 生成xml格式
     */
    private function _xml_format()
    {
        $str = '';
        foreach ($this->data as $val) {
            $str .= "<url>\n\t<loc>".$val['loc']."</loc>\n";
            $str .= "\t<lastmod>".date('Y-m-d', $val['lastmod'])."</lastmod>\n";
            $str .= "\t<changefreq>".$val['change_freq']."</changefreq>\n";
            $str .= "\t<priority>".$val['priority']."</priority>\n";
            $str .= "</url>\n";
        }

        return $str;
    }

    /**
     * 生成txt格式
     */
    private function _txt_format()
    {
        $str = '';
        foreach ($this->data as $val) {
            $str .= $val['loc']."\n";
        }

        return $str;
    }

    /**
     * 添加数据
     */
    private function _add_data($new_item)
    {
        $this->data[] = $new_item;
    }

    /**
     * 创建地图格式
     */
    private function _sitemap_item($loc, $lastmod = '', $change_freq = '', $priority = '')
    {
        $data                = array();
        $data['loc']         = $loc;
        $data['lastmod']     = $lastmod;
        $data['change_freq'] = $change_freq;
        $data['priority']    = $priority;

        return $data;
    }

}
